/*
 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.nio.channels;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.SocketOption;
import java.net.SocketAddress;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.nio.channels.spi.SelectorProvider;

/**
 * 面向流的监听套接字的可选通道。
 *
 * <p> 通过调用该类的open方法创建服务器-套接字通道。
 * 不能为任意预先存在的ServerSocket创建通道。
 * 新创建的服务器-套接字通道是打开的，但尚未绑定。
 * 尝试调用未绑定的服务器套接字通道的accept方法将导致抛出NotYetBoundException。
 * 可以通过调用这个类定义的一个bind方法来绑定服务器-套接字通道。
 *
 * <p> 套接字选项使用setOption方法进行配置。Server-socket通道支持以下选项:
 * <blockquote>
 * <table border summary="Socket options">
 *   <tr>
 *     <th>Option Name</th>
 *     <th>Description</th>
 *   </tr>
 *   <tr>
 *     <td> {@link java.net.StandardSocketOptions#SO_RCVBUF SO_RCVBUF} </td>
 *     <td> socket接收缓冲区的大小 </td>
 *   </tr>
 *   <tr>
 *     <td> {@link java.net.StandardSocketOptions#SO_REUSEADDR SO_REUSEADDR} </td>
 *     <td> 重用地址 </td>
 *   </tr>
 * </table>
 * </blockquote>
 * 还可能支持其他(特定于实现的)选项。
 *
 * <p> 服务器-套接字通道对于多个并发线程来说是安全的。
 * </p>
 *
 * @author Mark Reinhold
 * @author JSR-51 Expert Group
 * @since 1.4
 */

public abstract class ServerSocketChannel
    extends AbstractSelectableChannel
    implements NetworkChannel
{

    /**
     * 创建新实例
     *
     * @param  provider
     *         The provider that created this channel
     */
    protected ServerSocketChannel(SelectorProvider provider) {
        super(provider);
    }

    /**
     * 打开服务器套接字通道。
     *
     * <p> 新通道是通过调用系统范围默认java.nio.channels.spi.SelectorProvider的openServerSocketChannel方法创建的。
     *
     * <p> 新通道的套接字最初是未绑定的;
     * 它必须通过它的套接字的一个绑定方法绑定到特定的地址，然后连接才能被接受。
     *
     * @return  A new socket channel
     *
     * @throws  IOException
     *          If an I/O error occurs
     */
    public static ServerSocketChannel open() throws IOException {
        return SelectorProvider.provider().openServerSocketChannel();
    }

    /**
     * 返回一个操作集，标识此通道支持的操作。
     *
     * <p> 服务器-套接字通道仅支持接受新连接，因此此方法返回SelectionKey.OP_ACCEPT。
     * </p>
     *
     * @return  The valid-operation set
     */
    public final int validOps() {
        return SelectionKey.OP_ACCEPT;
    }


    // -- ServerSocket-specific operations --

    /**
     * 将通道的套接字绑定到本地地址，并将套接字配置为侦听连接。
     *
     * <p> 此方法的调用等价如下:
     * <blockquote><pre>
     * bind(local, 0);
     * </pre></blockquote>
     *
     * @param   local
     *          The local address to bind the socket, or {@code null} to bind
     *          to an automatically assigned socket address
     *
     * @return  This channel
     *
     * @throws  AlreadyBoundException               {@inheritDoc}
     * @throws  UnsupportedAddressTypeException     {@inheritDoc}
     * @throws  ClosedChannelException              {@inheritDoc}
     * @throws  IOException                         {@inheritDoc}
     * @throws  SecurityException
     *          If a security manager has been installed and its {@link
     *          SecurityManager#checkListen checkListen} method denies the
     *          operation
     *
     * @since 1.7
     */
    public final ServerSocketChannel bind(SocketAddress local)
        throws IOException
    {
        return bind(local, 0);
    }

    /**
     * 将通道的套接字绑定到本地地址，并将套接字配置为侦听连接。
     *
     * <p> 此方法用于建立套接字与本地地址之间的关联。一旦建立了关联，套接字就会一直绑定，直到通道关闭。
     *
     * <p> backlog参数是套接字上挂起的最大连接数。它的确切语义是特定于实现的。
     * 具体来说，实现可以设置最大长度，也可以选择完全忽略参数。
     * 如果backlog参数的值为0，或者为负值，则使用实现的指定默认值。
     *
     * @param   local
     *          The address to bind the socket, or {@code null} to bind to an
     *          automatically assigned socket address
     * @param   backlog
     *          The maximum number of pending connections
     *
     * @return  This channel
     *
     * @throws  AlreadyBoundException
     *          If the socket is already bound
     * @throws  UnsupportedAddressTypeException
     *          If the type of the given address is not supported
     * @throws  ClosedChannelException
     *          If this channel is closed
     * @throws  IOException
     *          If some other I/O error occurs
     * @throws  SecurityException
     *          If a security manager has been installed and its {@link
     *          SecurityManager#checkListen checkListen} method denies the
     *          operation
     *
     * @since 1.7
     */
    public abstract ServerSocketChannel bind(SocketAddress local, int backlog)
        throws IOException;

    /**
     * @throws  UnsupportedOperationException           {@inheritDoc}
     * @throws  IllegalArgumentException                {@inheritDoc}
     * @throws  ClosedChannelException                  {@inheritDoc}
     * @throws  IOException                             {@inheritDoc}
     *
     * @since 1.7
     */
    public abstract <T> ServerSocketChannel setOption(SocketOption<T> name, T value)
        throws IOException;

    /**
     * 检索与此通道相关联的服务器套接字。
     *
     * <p> 返回的对象不会声明没有在java.net.ServerSocket类中声明的任何公共方法。</p>
     *
     * @return  A server socket associated with this channel
     */
    public abstract ServerSocket socket();

    /**
     * 接受到此通道套接字的连接。
     *
     * <p> 如果该通道处于非阻塞模式，那么如果没有挂起的连接，该方法将立即返回null。
     * 否则，它将无限期阻塞，直到有新的连接可用或发生I/O错误。
     *
     * <p> 此方法返回的套接字通道(如果有的话)将处于阻塞模式，而不管该通道的阻塞模式是什么。
     *
     * <p> 此方法执行与java.net.ServerSocket类的accept方法完全相同的安全检查。
     * 也就是说，如果已经安装了安全管理器，那么对于每个新连接，
     * 此方法都会验证安全管理器的checkAccept方法是否允许连接的远程端点的地址和端口号。
     *
     * @return  The socket channel for the new connection,
     *          or <tt>null</tt> if this channel is in non-blocking mode
     *          and no connection is available to be accepted
     *
     * @throws  ClosedChannelException
     *          If this channel is closed
     *
     * @throws  AsynchronousCloseException
     *          If another thread closes this channel
     *          while the accept operation is in progress
     *
     * @throws  ClosedByInterruptException
     *          If another thread interrupts the current thread
     *          while the accept operation is in progress, thereby
     *          closing the channel and setting the current thread's
     *          interrupt status
     *
     * @throws  NotYetBoundException
     *          If this channel's socket has not yet been bound
     *
     * @throws  SecurityException
     *          If a security manager has been installed
     *          and it does not permit access to the remote endpoint
     *          of the new connection
     *
     * @throws  IOException
     *          If some other I/O error occurs
     */
    public abstract SocketChannel accept() throws IOException;

    /**
     * {@inheritDoc}
     * <p>
     * 如果设置了安全管理器，则使用本地地址和-1作为参数调用其checkConnect方法，以查看是否允许该操作。
     * 如果不允许该操作，则返回一个表示环回地址和通道套接字的本地端口的SocketAddress。
     *
     * @return  The {@code SocketAddress} that the socket is bound to, or the
     *          {@code SocketAddress} representing the loopback address if
     *          denied by the security manager, or {@code null} if the
     *          channel's socket is not bound
     *
     * @throws  ClosedChannelException     {@inheritDoc}
     * @throws  IOException                {@inheritDoc}
     */
    @Override
    public abstract SocketAddress getLocalAddress() throws IOException;

}
